"""
继承了Game的空类
"""
from game import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
import random

SCREEN_WIDTH = 960
SCREEN_HEIGHT = 720

#块大小
BLOCK_SIZE = 30

#移动方向
MOVE_DICT = {
    Qt.Key_Up     :(0, -1), # 上
    Qt.Key_Left   :(-1, 0), # 左
    Qt.Key_Down   :(0, 1), # 下
    Qt.Key_Right  :(1, 0) # 右
}
# 蛇头旋转方向
HEAD_ANGLE_DICT = {
    Qt.Key_Up    :180, # 上
    Qt.Key_Left  :90, # 左
    Qt.Key_Down  :0, # 下
    Qt.Key_Right :-90 # 右
}


class Snake:
    def __init__(self):
        self.direction = Qt.Key_Right  #方向
        self.is_cross_wall = True  #是否支持穿墙
        self.score = 0  #分数
        self.snake_body = [
            [6*BLOCK_SIZE,6*BLOCK_SIZE],
            [5*BLOCK_SIZE,6*BLOCK_SIZE],
            [4*BLOCK_SIZE,6*BLOCK_SIZE],
            [3*BLOCK_SIZE,6*BLOCK_SIZE]
        ]
        #加载蛇头图片
        self.head_img = QImage("img/head-red.png").scaled(BLOCK_SIZE, BLOCK_SIZE)
    def draw(self, qp: QPainter):
        # 取消边缘黑线
        qp.setPen(Qt.NoPen)
        # 绘制蛇身
        qp.setBrush(COLOR_BLUE)
        for x,y in self.snake_body[1:]:
            #圆角矩形
            qp.drawRoundedRect(x, y, BLOCK_SIZE, BLOCK_SIZE,5,5)
            
        # 绘制蛇头
        head_x,head_y = self.snake_body[0]
        # qp.setBrush(COLOR_GREEN)
        # qp.drawRect(head_x, head_y, BLOCK_SIZE, BLOCK_SIZE)
        #根据方向绘制蛇头
        angle = HEAD_ANGLE_DICT[self.direction]
        new_head_img = self.head_img.transformed(QTransform().rotate(angle))
        qp.drawImage(head_x, head_y, new_head_img)
      
    #   改变方向
    def change_direction(self, event: QKeyEvent):
        key = event.key()
        LR = [Qt.Key_Left, Qt.Key_Right]
        UD = [Qt.Key_Up, Qt.Key_Down]
        if key not in (LR + UD):
            if key == Qt.Key_Space:
                return
            print("无效按键")
            return
        
        if key == Qt.Key_Up:
            print("⬆️")
        elif key == Qt.Key_Left:
            print("⬅️")
        elif key == Qt.Key_Down:
            print("⬇️")
        elif key == Qt.Key_Right:
            print("➡️")
        
        # 限制上下左右  
        if key in UD and self.direction in UD:
            return
        elif key in LR and self.direction in LR:
            return   
        self.direction = key
        
    def move(self):
        new_move = MOVE_DICT[self.direction]
        #将蛇头复制一份
        new_head = self.snake_body[0][:]
        
        new_head[0] += new_move[0] * BLOCK_SIZE
        new_head[1] += new_move[1] * BLOCK_SIZE
        
        #判断是否越界（需要开启）
        if self.is_cross_wall:
            # 蛇头超出屏幕范围
            if new_head[0] < 0:
                new_head[0] = SCREEN_WIDTH - BLOCK_SIZE
            elif new_head[0] >= SCREEN_WIDTH:
                new_head[0] = 0
            if new_head[1] < 0:
                new_head[1] = SCREEN_HEIGHT - BLOCK_SIZE
            elif new_head[1] >= SCREEN_HEIGHT:
                new_head[1] = 0

        
        # 插入新蛇头
        self.snake_body.insert(0,new_head)
        # 删除蛇尾
        self.snake_body.pop()
        
    def grow(self):
        # 蛇生长，复制一份蛇尾
        self.snake_body.append(self.snake_body[-1][:])
        self.score += 1
    
class Food:
    def __init__(self,x,y,num):
        """
        x:[0,31] *BLOCK_SIZE
        y:[0,23] *BLOCK_SIZE
        """
        self.node = [x,y] 
        self.num = num
        #加载食物图片
        self.bird = QImage("img/bird.png").scaled(BLOCK_SIZE, BLOCK_SIZE)
        self.frog = QImage("img/frog.png").scaled(BLOCK_SIZE, BLOCK_SIZE)
        self.mouse = QImage("img/mouse.png").scaled(BLOCK_SIZE, BLOCK_SIZE)
    def draw(self, qp: QPainter):
        x,y = self.node
        if self.num == 1:
            qp.drawImage(x, y, self.bird)
        elif self.num == 2:
            qp.drawImage(x, y, self.frog)
        elif self.num == 3:
            qp.drawImage(x, y, self.mouse)

class SnakeGame(Game):
    
    def __init__(self):
        super().__init__()
        # 设置标题
        self.setWindowTitle("SnakeGame")
        # 设置窗口尺寸, 并禁止拖拽修改窗口尺寸
        self.setFixedSize(SCREEN_WIDTH, SCREEN_HEIGHT)
        # 设置窗口图标
        self.setWindowIcon(QIcon("img/icon.png"))
        #   加载背景
        self.bg = QImage("img/bg.png").scaled(SCREEN_WIDTH, SCREEN_HEIGHT)
        # 生成地图网格点
        self.map_points = []
        for x in range(0, SCREEN_WIDTH, BLOCK_SIZE):
            for y in range(0, SCREEN_HEIGHT, BLOCK_SIZE):
                self.map_points.append([x,y])
        
        # 设置帧率
        self.set_fps(5)
        
        self.snake : Snake = None
        self.food : Food = None
        
        
    def keyPressEvent(self, event: QKeyEvent):
        """处理按键事件
        """
        super().keyPressEvent(event)
        if self.snake is not None:
            self.snake.change_direction(event)
    
    def generate_new_food(self):
        """ 生成新的食物
            推导式过滤掉身体部分的点
        """
        new_map = [node for node in self.map_points if node not in self.snake.snake_body]
        #蛇占据整个地图
        if len(new_map) == 0:
            return
        #随机选择一个点
        x,y = random.choice(new_map)
        #随机生成一种食物
        num = random.randint(1,3)
        self.food = Food(x,y,num)
        
    def on_time_event(self, event):
        """处理每帧时间事件
        """
        #移动蛇
        self.snake.move()
        #判断是否吃到食物
        head = self.snake.snake_body[0]
        if head == self.food.node:
            print("eat food")
            # 蛇生长
            self.snake.grow()
            # 生成新的食物
            self.generate_new_food()
        #碰撞判断
        head_x,head_y = head
        if head_x >= SCREEN_WIDTH or head_x < 0 or head_y >= SCREEN_HEIGHT or head_y < 0:
            print("撞墙了")
            self.is_game_over = True
        if head in self.snake.snake_body[1:]:
            print("撞到自己了")
            self.is_game_over = True
     
        
        
    def draw_content(self, qp: QPainter):
        """绘制界面内容
        :param qp: 画笔
        """
        # 画笔抗锯齿
        qp.setRenderHint(QPainter.Antialiasing)
        # 绘制背景
        qp.drawImage(0, 0, self.bg)
        # 绘制网格线
        qp.setPen(COLOR_GRAY)
        # 画横线
        for y in range(0, SCREEN_HEIGHT, BLOCK_SIZE):
            qp.drawLine(0, y, SCREEN_WIDTH, y)
        # 画竖线
        for x in range(0, SCREEN_WIDTH, BLOCK_SIZE):
            qp.drawLine(x, 0, x, SCREEN_HEIGHT)
        
        # 绘制蛇头&蛇身
        self.snake.draw(qp)
        
        # 绘制食物
        self.food.draw(qp)
        
        # 绘制分数
        #左上角绘制白色的文字 score:分数
        qp.setPen(Qt.white)
        qp.setFont(QFont("Arial", 20))
        qp.drawText(30, 50, f"score:{self.snake.score}")
        
        #   游戏结束
        if self.is_game_over:
            qp.setPen(Qt.white)
            qp.setFont(QFont("Arial", 40))
            qp.drawText(200, SCREEN_HEIGHT/2, "Game Over")
            # 按空格重新开始
            qp.setFont(QFont("Arial", 20))
            qp.drawText(200, SCREEN_HEIGHT/2 + 100, "Press Space to Restart")
        
    
    def start_game(self):
        """游戏开始前的初始化
        """
        self.snake = Snake()
        self.generate_new_food()
        
        super().start_game()
    

if __name__ == '__main__':
    SnakeGame.start()